﻿using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.IO;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Threading;
using System.Text.RegularExpressions;

namespace 任务管理器
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class 任务管理器侧边栏 : Window
    {
        #region 初始化逻辑
        string 配置文件名 = "";
        界面 界面设定 = new 界面();
        Dictionary<string, TreeViewItem> 界面数据 = new Dictionary<string, TreeViewItem>();
        List<任务套> 任务套组 = new List<任务套>();
        string 配置文件保存路径 = 数据集.配置文件保存路径;
        bool 主程序运行 = true;
        /// <summary>
        /// 窗口启动时逻辑
        /// </summary>
        public 任务管理器侧边栏()
        {
            //设定基础内容
            InitializeComponent();
            设定窗口位置(65, 100);
            清空任务内容();
            //设定数据
            读取任务项();
            更新任务界面();
            设定标题栏合计总数();
            打开自动更新UI();
        }
        #endregion
        #region 界面基础信息设定
        /// <summary>
        ///  设定窗口在屏幕中的位置
        /// </summary>
        /// <param name="高度百分比">从上到下的高度百分比</param>
        /// <param name="宽度百分比">从左到右的宽度百分比</param>
        private void 设定窗口位置(double 高度百分比, double 宽度百分比)
        {

            //设定不在任务栏显示该窗口
            this.ShowInTaskbar = false;
            //获取当前显示设定
            界面设定.屏幕长度 = System.Windows.SystemParameters.PrimaryScreenWidth;
            界面设定.屏幕高度 = System.Windows.SystemParameters.PrimaryScreenHeight;
            //设置窗口位置
            this.Top = 界面设定.屏幕高度 * (高度百分比 * 0.01) - this.Height;
            this.Left = 界面设定.屏幕长度 * (宽度百分比 * 0.01) - this.Width;
            this.Topmost = true;
        }
        #endregion
        #region 任务内容设定
        public void 清空任务内容()
        {
            任务项集.Items.Clear();
        }
        public void 设定标题栏合计总数(int 合计数)
        {
            标题栏.Text = $"任务列表 ({合计数})";
        }
        public void 设定标题栏合计总数()
        {
            标题栏.Text = $"任务列表 ({任务套组.FindAll(信息 => 信息.任务信息.任务状态 != 任务.任务执行状态.已完成 && 信息.任务信息.任务状态 != 任务.任务执行状态.已失败).Count})";
            if (任务套组.Count > 0) { } else { 标题栏.Text = $"任务列表 (0)"; }
        }
        public void 读取任务项()
        {
            任务套组.Clear();
            if (Directory.Exists(配置文件保存路径) == false) { Directory.CreateDirectory(配置文件保存路径); }
            DirectoryInfo 任务资料文件夹 = new DirectoryInfo(配置文件保存路径);
            FileInfo[] 任务资料组 = 任务资料文件夹.GetFiles();
            配置项 配置 = new 配置项();
            文件 文件 = new 文件();
            foreach (FileInfo 任务资料 in 任务资料组)
            {
                //跳过非cfg文件
                if (任务资料.Extension.Contains("cfg") == false) { continue; }
                任务 信息 = new 任务();
                //打开任务资料文件
                信息.任务名称 = 配置.读取(任务资料.FullName, "基础信息", "名称", "读取失败");
                if (信息.任务名称 == "读取失败") { File.Delete(任务资料.FullName); continue; }
                信息.任务类别 = 配置.读取(任务资料.FullName, "基础信息", "类别", "读取失败");
                信息.任务状态 = (任务.任务执行状态)Enum.Parse(typeof(任务.任务执行状态), 配置.读取(任务资料.FullName, "基础信息", "任务状态", "读取失败"));
                信息.任务进度 = double.Parse(配置.读取(任务资料.FullName, "基础信息", "任务进度", "0"));
                信息.任务时间模式 = (任务.时间模式)Enum.Parse(typeof(任务.时间模式), 配置.读取(任务资料.FullName, "高级设定", "时间模式", Enum.GetName(typeof(任务.时间模式), 任务.时间模式.不使用)));
                信息.任务添加时间 = DateTime.Parse(配置.读取(任务资料.FullName, "高级设定", "启动时间", "2000-1-1"));
                信息.任务时限 = DateTime.Parse(配置.读取(任务资料.FullName, "高级设定", "时间设定", "2000-1-1"));
                信息.是否使用命令行 = bool.Parse(配置.读取(任务资料.FullName, "高级设定", "启用命令行", "false"));
                信息.命令行 = 配置.读取(任务资料.FullName, "高级设定", "命令行内容", "读取失败");
                信息.任务描述 = 文件.读入文件_快速(配置文件保存路径 + "\\" + Path.GetFileNameWithoutExtension(任务资料.Name) + ".tdf", Encoding.GetEncoding("GB2312"));
                信息.是否有子任务 = bool.Parse(配置.读取(任务资料.FullName, "任务子项", "是否启用", "false"));
                信息.是否使用文本行 = bool.Parse(配置.读取(任务资料.FullName, "高级设定", "启用文本行", "false"));
                信息.文本行 = 配置.读取(任务资料.FullName, "高级设定", "文本行内容", "");
                信息.当前任务项 = int.Parse(配置.读取(任务资料.FullName, "基础信息", "当前项", "0"));
                信息.最高任务项 = int.Parse(配置.读取(任务资料.FullName, "基础信息", "最高项", "0"));
                信息.配置文件路径 = 任务资料.FullName;
                任务套组.Add(new 任务套 { 任务信息 = 信息 });
            }


        }
        public void 直接完成任务(string 任务名称, bool 是否完成)
        {
            配置项 配置 = new 配置项();
            string 配置文件 = $"{ 配置文件保存路径 }\\{任务名称}.cfg";
            if (配置.读取(配置文件, "基础信息", "任务状态", "错误") == 任务.任务执行状态.已完成.ToString())
            {
                return;
            }

            配置.写入(配置文件, "基础信息", "任务状态", 任务.任务执行状态.已完成.ToString());
            配置.写入(配置文件, "基础信息", "任务进度", "100");
            读取任务项();
            更新任务界面();
        }
        public void 直接失败任务(string 任务名称, bool 是否完成)
        {
            配置项 配置 = new 配置项();
            string 配置文件 = $"{ 配置文件保存路径 }\\{任务名称}.cfg";
            if (配置.读取(配置文件, "基础信息", "任务状态", "错误") == 任务.任务执行状态.已失败.ToString())
            {
                return;
            }

            配置.写入(配置文件, "基础信息", "任务状态", 任务.任务执行状态.已失败.ToString());
            读取任务项();
            更新任务界面();
        }
        public void 更新任务界面()
        {
            //清理

            任务项集.Items.Clear();

            界面数据.Clear();
            foreach (var 信息 in 任务套组)
            {
                #region 子树创建
                //若子树不存在则新建
                var 子树是否存在 = 界面数据.ContainsKey($"{信息.任务信息.任务类别}_主树");
                if (子树是否存在 == false)
                {
                    TreeViewItem 新子树 = new TreeViewItem();
                    新子树.Header = 信息.任务信息.任务类别;
                    TreeViewItem 已结束 = new TreeViewItem(); 已结束.Header = "已结束"; 新子树.Items.Add(已结束);

                    任务项集.Items.Add(新子树);

                    界面数据.Add($"{信息.任务信息.任务类别}_主树", 新子树);
                    界面数据.Add($"{信息.任务信息.任务类别}_已结束", 已结束);
                }
                #endregion

                #region 任务信息块创建
                //添加任务到该树
                单任务模具 任务信息块 = new 单任务模具();
                任务信息块.任务名 = 信息.任务信息.任务名称;
                if (信息.任务信息.任务状态 == 任务.任务执行状态.已完成) { 任务信息块.完成状态 = true; }
                任务信息块.进度条 = (int)信息.任务信息.任务进度;
                任务信息块.任务详情 = $"{信息.任务信息.任务名称}\r\n" + 信息.任务信息.任务描述;
                //进度条样式设置
                if (信息.任务信息.任务状态 == 任务.任务执行状态.正在进行) { 任务信息块.进度条样式(单任务模具.进度条类型.进行中); }
                if (信息.任务信息.任务状态 == 任务.任务执行状态.已完成) { 任务信息块.进度条样式(单任务模具.进度条类型.进行中); }
                if (信息.任务信息.任务状态 == 任务.任务执行状态.暂停中 || 信息.任务信息.任务状态 == 任务.任务执行状态.正在等待) { 任务信息块.进度条样式(单任务模具.进度条类型.等待中); }
                if (信息.任务信息.任务状态 == 任务.任务执行状态.已失败 || 信息.任务信息.任务状态 == 任务.任务执行状态.阻塞中) { 任务信息块.进度条样式(单任务模具.进度条类型.错误); }
                //事件绑定
                任务信息块.打开编辑窗 = 编辑任务;
                任务信息块.完成任务 = 直接完成任务;
                //判断时间
                if (DateTime.Now > 信息.任务信息.任务时限 && 信息.任务信息.任务时间模式 != 任务.时间模式.不使用)
                {
                    信息.任务信息.任务状态 = 任务.任务执行状态.已完成;
                }
                //加入树
                if (信息.任务信息.任务状态 == 任务.任务执行状态.已完成 || 信息.任务信息.任务状态 == 任务.任务执行状态.已失败)
                {
                    信息.任务模具 = 任务信息块;
                    int 索引 = 界面数据[$"{信息.任务信息.任务类别}_已结束"].Items.Add(任务信息块);
                    continue;
                }
                信息.任务模具 = 任务信息块;
                界面数据[$"{信息.任务信息.任务类别}_主树"].Items.Add(任务信息块);

                #endregion


            }

            界面设定.需要重载 = true;
            设定标题栏合计总数();

        }
        #region 任务高级特性
        static string 从文本更新值(任务套 任务,string 文本串)
        {
            任务管理器.正则 正则 = new 任务管理器.正则();
            string 文件名 = "";
            string 命令组 = "";
            string 文件内容 = "";
            int 当前项 = 0;
            int 最高项 = 100;
            int 进度 = 0;

            //读取文件名与命令组

            Regex 文本匹配器 = new Regex(@"\[(.*)\](.*)");
            var 文本匹配集 = 文本匹配器.Matches(文本串);
            if (文本匹配集.Count == 0) { return "不正确的文本串"; }
            文件名 = 文本匹配集[0].Groups[1].Value;
            命令组 = 文本匹配集[0].Groups[2].Value;

            //处理文件与命令组
            if (File.Exists(文件名) == false) { return "文件名不正确"; }
            FileInfo 文件信息 = new FileInfo(文件名);
            if (文件信息.LastWriteTime == 任务.任务信息.文本文件更新时间) { return "文件未更新"; }
            else { 任务.任务信息.文本文件更新时间 = 文件信息.LastWriteTime; }
            文件内容 = File.ReadAllText(文件名);
            var 命令集 = 命令组.Split('|');
            int 指针 = 0;
            while (指针 < 命令集.Length)
            {
                string 项名 = 命令集[指针];
                string 正则式 = 命令集[指针 + 1];
                Regex 匹配器 = new Regex(正则式);
                var 匹配集 = 匹配器.Matches(文件内容);
                if (项名 == "当前项") { 当前项 = int.Parse(匹配集[0].Groups[1].Value); 任务.任务信息.当前任务项 = 当前项; }
                if (项名 == "最高项") { 最高项 = int.Parse(匹配集[0].Groups[1].Value); 任务.任务信息.最高任务项 = 最高项; }
                if (项名 == "进度") { 进度 = int.Parse(匹配集[0].Groups[1].Value); 任务.任务信息.任务进度 = 进度; }
                指针 += 2;
                
            }
            
           
            
            return $"文件名：{文件名}\r\n命令组：{命令组}\r\n当前：{当前项} 最高：{最高项} 进度：{进度}";
        }
        #endregion
        #region UI刷新
        /// <summary>
        /// 线程创建器
        /// </summary>
        public void 打开自动更新UI()
        {
            Thread 精确定时更新 = new Thread(精确任务模具更新线程);
            精确定时更新.TrySetApartmentState(ApartmentState.STA);
            精确定时更新.Start();
            Thread 普通定时更新 = new Thread(普通任务模具更新线程);
            普通定时更新.TrySetApartmentState(ApartmentState.STA);
            普通定时更新.Start();

        }
        public void 精确任务模具更新线程()
        {

            List<任务套> 任务组 = new List<任务套>();
            while (this.IsInitialized)
            {
                if (主程序运行 == false) { return; }
                // 重载并处理过期任务
                if (界面设定.需要重载)
                {
                    任务组.Clear();
                    
                    var 任务组_旧 = 任务套组.FindAll(任务集 => 任务集.任务信息.任务时间模式 != 任务.时间模式.不使用 && 任务集.任务信息.任务状态 != 任务.任务执行状态.已完成);
                    foreach (var 任务 in 任务组_旧)
                    {
                        var 任务时限 = 任务.任务信息.任务时限;
                        if (DateTime.Now > 任务时限)
                        {
                            if (任务.任务信息.任务时间模式 == 任务管理器.任务.时间模式.DeadLine时间模式)
                            { 任务.任务信息.任务状态 = 任务管理器.任务.任务执行状态.已失败; 直接失败任务(任务.任务信息.任务名称, true); }
                            if (任务.任务信息.任务时间模式 == 任务管理器.任务.时间模式.正计时间模式 || 任务.任务信息.任务时间模式 == 任务管理器.任务.时间模式.倒计时间模式)
                            { 任务.任务信息.任务状态 = 任务管理器.任务.任务执行状态.已完成; 直接完成任务(任务.任务信息.任务名称, true); }
                            continue;
                        }
                        任务组.Add(任务);
                    }
                }
                更新任务模具_依时限(任务组);
                Thread.Sleep(界面设定.精确更新间隔);
            }
        }
        public void 普通任务模具更新线程()
        {
          
            List<任务套> 任务组 = new List<任务套>() ;
            while (this.IsInitialized)
            {
                if (主程序运行 == false) { return; }
                if (界面设定.需要重载)
                {
                    界面设定.需要重载 = false;
                    任务组 = 任务套组.FindAll(任务集 => 任务集.任务信息.是否使用文本行 == true);
                }
                    更新任务模具_依文本(任务组);
                    
                    Thread.Sleep(界面设定.普通更新间隔);
            }
            

        }
        public void 更新任务模具_依文本(List<任务套> 任务组)
        {
            配置项 配置 = new 配置项();
            foreach (var 任务 in 任务组)
            {
                从文本更新值(任务, 任务.任务信息.文本行);
                if (File.Exists(任务.任务信息.配置文件路径) == false) { return; }
                this.Dispatcher.BeginInvoke((ThreadStart)delegate ()
                {
                任务.任务模具.进度.Value = ((double)任务.任务信息.当前任务项 / (double)任务.任务信息.最高任务项)*100;
                配置.写入(任务.任务信息.配置文件路径, "基础信息", "任务进度", 任务.任务信息.任务进度.ToString());
                配置.写入(任务.任务信息.配置文件路径, "基础信息", "当前项", 任务.任务信息.当前任务项.ToString());
                配置.写入(任务.任务信息.配置文件路径, "基础信息", "最高项", 任务.任务信息.最高任务项.ToString());
                });
            }
        
        }

        public void 更新任务模具_依时限(List<任务套> 任务组)
        {
            //判断是否需要刷新
            时间辅助 时间 = new 时间辅助();
            if (任务组.Count == 0) { Console.WriteLine("无任务"); return; }
            #region 分组
            var 正倒计任务组 = 任务组.FindAll(任务集 => 任务集.任务信息.任务时间模式 == 任务管理器.任务.时间模式.正计时间模式 || 任务集.任务信息.任务时间模式 == 任务管理器.任务.时间模式.倒计时间模式);
            var DeadLine任务组 = 任务组.FindAll(任务集 => 任务集.任务信息.任务时间模式 == 任务管理器.任务.时间模式.DeadLine时间模式);

            #endregion
            #region 正倒计任务组
            foreach (var 任务 in 正倒计任务组)
            {
                var 任务开始时间 = 任务.任务信息.任务添加时间;
                var 任务结束时间 = 任务.任务信息.任务时限;
                var 百分比设定 = 时间.计算时间百分比(任务开始时间, 任务结束时间);
                if (任务.任务信息.任务时间模式 == 任务管理器.任务.时间模式.正计时间模式) { 百分比设定 = 100 - 百分比设定; }
                //超时处理
                if (DateTime.Now > 任务.任务信息.任务时限)
                {
                    //该模块可单独拆分
                    //该模块可单独拆分
                    //该模块可单独拆分
                    this.Dispatcher.Invoke((ThreadStart)delegate ()
                    {
                        任务.任务模具.进度.Value = 100;
                        任务.任务信息.任务状态 = 任务管理器.任务.任务执行状态.已完成;

                        界面数据[$"{任务.任务信息.任务类别}_主树"].Items.Remove(任务.任务模具);
                        界面数据[$"{任务.任务信息.任务类别}_已结束"].Items.Add(任务.任务模具);
                        任务.任务模具.完成框.IsChecked = true;
                        直接完成任务(任务.任务信息.任务名称, true);

                    });
                    任务组.Remove(任务);
                    continue;
                }
                this.Dispatcher.BeginInvoke((ThreadStart)delegate ()
                {
                    任务.任务模具.进度.Value = (int)百分比设定;

                });


            }

            #endregion
            #region DeadLine任务组
            foreach (var 任务 in DeadLine任务组)
            {
                var 当前时间 = DateTime.Now;
                var 任务开始时间 = 任务.任务信息.任务添加时间;
                var 任务结束时间 = 任务.任务信息.任务时限;
                var 时间间隔 = 任务结束时间.Subtract(当前时间);
                var 百分比设定 = 时间.计算时间百分比(任务开始时间, 任务结束时间);
                this.Dispatcher.BeginInvoke((ThreadStart)delegate ()
                {
                    if (百分比设定 < 20)
                    {
                        任务.任务模具.任务名称.Text = $"{任务.任务信息.任务名称} | 剩余：{百分比设定}%";
                    }
                    if (时间间隔 < TimeSpan.FromMinutes(5))
                    {
                        任务.任务模具.任务名称.Text = $"{任务.任务信息.任务名称} | 剩余：{时间间隔.ToString(@"mm\:ss")}";
                    }
                    任务.任务模具.总成.Content = $"{任务.任务信息.任务名称}\r\n{任务.任务信息.任务描述}\r\n[ ! ] 距完成时限还有{时间间隔.ToString(@"hh\:mm\:ss")}({百分比设定}%)";
                });
                if (DateTime.Now > 任务.任务信息.任务时限)
                {
                    //该模块可单独拆分
                    //该模块可单独拆分
                    //该模块可单独拆分
                    this.Dispatcher.Invoke((ThreadStart)delegate ()
                    {
                        任务.任务信息.任务状态 = 任务管理器.任务.任务执行状态.已完成;
                        界面数据[$"{任务.任务信息.任务类别}_主树"].Items.Remove(任务.任务模具);
                        界面数据[$"{任务.任务信息.任务类别}_已结束"].Items.Add(任务.任务模具);
                        任务.任务模具.完成框.IsChecked = false;
                        直接失败任务(任务.任务信息.任务名称, false);

                    });
                    任务组.Remove(任务);
                    continue;
                }
            }
            #endregion

        }
        public void 更新任务界面(List<任务套> 任务套)
        {


        }
        #endregion 
        #endregion
        #region 按钮事件设定
        private void 展开按钮_Click(object sender, RoutedEventArgs e)
        {
            if (界面设定.界面收缩 == 取界面设置.界面展开状态.已展开) { 界面设定.界面收缩 = 取界面设置.界面展开状态.已收起; this.Height = 36; return; }
            if (界面设定.界面收缩 == 取界面设置.界面展开状态.已收起) { 界面设定.界面收缩 = 取界面设置.界面展开状态.已展开; this.Height = 450; return; }

        }
        private void 新建任务菜单_Click(object sender, RoutedEventArgs e)
        {
            任务编辑窗口 编辑新任务 = new 任务编辑窗口(任务套组);
            编辑新任务.重读任务 = 读取任务项;
            编辑新任务.重读信息 = 更新任务界面;
            编辑新任务.Show();
        }


        public void 编辑任务(string 任务名称)
        {

            任务编辑窗口 编辑新任务 = new 任务编辑窗口(任务套组, 任务名称);
            编辑新任务.重读任务 = 读取任务项;
            编辑新任务.重读信息 = 更新任务界面;
            编辑新任务.Show();
        }





        #endregion

        private void Window_MouseLeave(object sender, MouseEventArgs e)
        {
            if (任务项集.SelectedItem == null) { return; }
            this.Dispatcher.Invoke((ThreadStart)delegate ()
            {
                try
                {
                    var a = (TreeViewItem)任务项集.SelectedItem;
                    a.IsSelected = false;
                }
                catch
                {
             
                    更新任务界面();
                }


            });
        }

        ~任务管理器侧边栏()
            {
            Console.WriteLine("待办已析构");
        
            }

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            Console.WriteLine("正在准备关闭窗口");
            主程序运行 = false;
            GC.Collect();
        }
    }
}
